//This class is intended to create a serial reader to feed the serial parser.
//This code was derived from the wikibooks entry on serial programming in linux here:
//http://en.wikibooks.org/wiki/Serial_Programming:Serial_Linux#termios
//Which is licensed under Creative Commons Share and Share Alike (3.0) as seen here:
//http://creativecommons.org/licenses/by-sa/3.0/

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <QDateTime>
#include "serialhandler.h"

serialHandler::serialHandler(QObject *parent) :
    QObject(parent)
{
    portName = "dev/ttyACM0";
}


bool serialHandler::openSerial()
{
    //unsigned char c='D';

    //printf("Please start with %s /dev/ttyS1 (for example)\n",argv[0]);
    //removed since this is terminal based
    memset(&stdio,0,sizeof(stdio));
    stdio.c_iflag=0;
    stdio.c_oflag=0;
    stdio.c_cflag=0;
    stdio.c_lflag=0;
    stdio.c_cc[VMIN]=1;
    stdio.c_cc[VTIME]=0;
    tcsetattr(STDOUT_FILENO,TCSANOW,&stdio);
    tcsetattr(STDOUT_FILENO,TCSAFLUSH,&stdio);
    fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);       // make the reads non-blocking

    memset(&tio,0,sizeof(tio));
    tio.c_iflag=0;
    tio.c_oflag=0;
    tio.c_cflag=CS8|CREAD|CLOCAL;           // 8n1, see termios.h for more information
    tio.c_lflag=0;
    tio.c_cc[VMIN]=1;
    tio.c_cc[VTIME]=5;

    tty_fd = 0;
    tty_fd=open(portName.toLocal8Bit().data(), O_RDWR | O_NONBLOCK);  //maybe &portname portName.toStdString().c_str()
    if(tty_fd == -1)
    {
        //do something because the stream failed to start
        QString error = "Port failed to open on ";  //portName & " at " & QTime::currentTime().toString();
        error.append(portName);
        error.append(" at ");
        error.append(QTime::currentTime().toString());
//        error.append("\nCode: ");
//        error.append(tty_fd);
        emit logMessage(error);
        //also need to do something so that the start button becomes enabled again
        emit serialFailure();
        return false;
    }
    else
    {
        cfsetospeed(&tio,B57600);            // 115200 baud originally
        cfsetispeed(&tio,B57600);            // 115200 baud

        tcsetattr(tty_fd,TCSANOW,&tio);
        QString success = "Port opened on ";
        success.append(portName);
        success.append(" at ");
        success.append(QTime::currentTime().toString());
        emit logMessage(success);
        return true;    //actually needs to return whether the stream opened sucessfully or not
    }

}

bool serialHandler::serialStream()
{
    char data[255];
    if (read(tty_fd, &data, 1) > 0)
    {
        //process serial

        //read(tty_fd, const char *readIn, 255);
        QByteArray tmpArray(data);  //read(tty_fd,&data, 1)];
        emit serialBytes(tmpArray);
    }
    else return false;
    //instead of using this while loop, the serial stream function should be in a loop that check whether the stopSerial signal has been sent first
    //unsigend char c starts = to 'D'
    //while (c!='q')
    //{
            //if (read(tty_fd,&c,1)>0)        write(STDOUT_FILENO,&c,1);              // if new data is available on the serial port, print it out
            //if (read(STDIN_FILENO,&c,1)>0)  write(tty_fd,&c,1);                     // if new data is available on the console, send it to the serial port
            //these two lines need to be changed to update the serialLogText text box
    //}

    //we actually need to probably make this a bool. The function itself would operate on some string that is passed in.
    //if no errors or maybe if data was available then return true
    return true;
}

void serialHandler::closeSerial()
{
    close(tty_fd);
    tty_fd = 0;
    QString success = "Port closed on ";
    success.append(portName);
    success.append(" at ");
    success.append(QTime::currentTime().toString());
    emit logMessage(success);
}

void serialHandler::setPortName(QString newPortName)    //char *newPortName)
{
    portName = newPortName;  //.toStdString().c_str();
}

void serialHandler::setBaud(long baud)
{
    //doesn't acutally work yet.
}



//ORIGINAL
//int main(int argc,char** argv)
//{
//    struct termios tio;
//    struct termios stdio;
//    int tty_fd;
//    fd_set rdset;

//    unsigned char c='D';

//    printf("Please start with %s /dev/ttyS1 (for example)\n",argv[0]);
//    memset(&stdio,0,sizeof(stdio));
//    stdio.c_iflag=0;
//    stdio.c_oflag=0;
//    stdio.c_cflag=0;
//    stdio.c_lflag=0;
//    stdio.c_cc[VMIN]=1;
//    stdio.c_cc[VTIME]=0;
//    tcsetattr(STDOUT_FILENO,TCSANOW,&stdio);
//    tcsetattr(STDOUT_FILENO,TCSAFLUSH,&stdio);
//    fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);       // make the reads non-blocking

//    memset(&tio,0,sizeof(tio));
//    tio.c_iflag=0;
//    tio.c_oflag=0;
//    tio.c_cflag=CS8|CREAD|CLOCAL;           // 8n1, see termios.h for more information
//    tio.c_lflag=0;
//    tio.c_cc[VMIN]=1;
//    tio.c_cc[VTIME]=5;

//    tty_fd=open(argv[1], O_RDWR | O_NONBLOCK);
//    cfsetospeed(&tio,B57600);            // 115200 baud
//    cfsetispeed(&tio,B57600);            // 115200 baud

//    tcsetattr(tty_fd,TCSANOW,&tio);
//    while (c!='q')
//    {
//            if (read(tty_fd,&c,1)>0)        write(STDOUT_FILENO,&c,1);              // if new data is available on the serial port, print it out
//            if (read(STDIN_FILENO,&c,1)>0)  write(tty_fd,&c,1);                     // if new data is available on the console, send it to the serial port
//    }

//    close(tty_fd);
//}
